package com.bsg.upm.service;

import java.util.List;
import java.util.Map;

import javax.annotation.Resource;

import org.apache.commons.lang3.StringUtils;
import org.apache.http.HttpStatus;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import com.alibaba.fastjson.JSONArray;
import com.bsg.upm.check.CheckResult;
import com.bsg.upm.check.SiteCheck;
import com.bsg.upm.constant.DictConstants;
import com.bsg.upm.constant.DictTypeConstants;
import com.bsg.upm.constant.OperateDictConstants;
import com.bsg.upm.constant.OperateDictTypeConstants;
import com.bsg.upm.dto.SiteDto;
import com.bsg.upm.entity.SiteEntity;
import com.bsg.upm.entity.UserEntity;
import com.bsg.upm.exception.APIException;
import com.bsg.upm.http.RespJson;
import com.bsg.upm.http.RespJsonFactory;
import com.bsg.upm.util.DateUtils;
import com.bsg.upm.util.PrimaryKeyUtils;
import com.google.common.net.HostAndPort;
import com.orbitz.consul.Consul;
import com.orbitz.consul.HealthClient;
import com.orbitz.consul.model.State;
import com.orbitz.consul.model.health.HealthCheck;

/**
 * 站点管理业务处理类
 * 
 * @author HCK
 *
 */
@Service
public class SiteService extends BaseService {

	@Resource
	private SiteCheck siteCheck;

	/**
	 * 站点查询
	 * 
	 * @param paramMap
	 *            请求参数
	 * @return RespJson请求结果对象
	 * @throws APIException
	 *             API异常处理类
	 */
	public RespJson list(Map<String, Object> paramMap) throws APIException {
		try {
			// 结果集
			JSONArray results = new JSONArray();

			// 获取指定条件的站点
			List<SiteEntity> sites = siteDao.list(paramMap);

			for (SiteEntity site : sites) {
				// 构建站点展示对象
				SiteDto siteDto = getShowDto(site, false);
				results.add(siteDto);
			}

			return RespJsonFactory.buildOK(results);
		} catch (Exception e) {
			logger.error("站点查询异常", e);
			throw new APIException("站点查询异常:" + e.getMessage());
		}
	}

	/**
	 * 站点详情
	 * 
	 * @param siteId
	 *            站点编码
	 * @return RespJson请求结果对象
	 * @throws APIException
	 *             API异常处理类
	 */
	public RespJson get(String siteId) throws APIException {
		try {
			// 获取指定的站点
			SiteEntity site = siteDao.get(siteId);

			if (site == null) {
				return RespJsonFactory.build(HttpStatus.SC_GONE, "该站点不存在");
			}

			// 构建站点展示对象
			SiteDto siteDto = getShowDto(site, true);

			return RespJsonFactory.buildOK(siteDto);
		} catch (Exception e) {
			logger.error("站点查询异常", e);
			throw new APIException("站点查询异常:" + e.getMessage());
		}
	}

	/**
	 * 站点新增
	 * 
	 * @param paramMap
	 *            请求参数
	 * @return RespJson请求结果对象
	 * @throws APIException
	 *             API异常处理类
	 */
	@Transactional(rollbackFor = APIException.class)
	public RespJson save(Map<String, Object> paramMap) throws APIException {
		// 操作动作
		String operateAcion = OperateDictConstants.ACTION_REGISTER;
		String operateAcionText = dictTypeCache.getTextFromCache(OperateDictTypeConstants.OPERATE_ACTION, operateAcion);
		try {
			// 新增检查
			CheckResult chkRS = siteCheck.checkSave(paramMap);
			if (chkRS.isError()) {
				return RespJsonFactory.build(chkRS.getStatus(), chkRS.getErrorMsg());
			}

			// 构建站点对象
			SiteEntity site = buildSite(paramMap);
			siteDao.save(site);

			// 保存操作日志
			saveOperateLog(OperateDictConstants.MODEL_SITE, operateAcion, site.getId(), site.getName(),
					site.getCreateDateTime());

			return RespJsonFactory.buildCreated();
		} catch (Exception e) {
			logger.error("站点" + operateAcionText + "异常", e);
			throw new APIException("站点" + operateAcionText + "异常" + e.getMessage());
		}
	}

	/**
	 * 站点注销
	 * 
	 * @param id
	 *            站点编码
	 * @return RespJson请求结果对象
	 * @throws APIException
	 *             API异常处理类
	 */
	@Transactional(rollbackFor = APIException.class)
	public RespJson remove(String id) throws APIException {
		// 操作动作
		String operateAcion = OperateDictConstants.ACTION_DEREGISTER;
		String operateAcionText = dictTypeCache.getTextFromCache(OperateDictTypeConstants.OPERATE_ACTION, operateAcion);
		try {
			// 获取指定的站点
			SiteEntity site = siteDao.get(id);

			// 删除检查
			CheckResult chkRS = siteCheck.checkRemove(site);
			if (chkRS.isError()) {
				return RespJsonFactory.build(chkRS.getStatus(), chkRS.getErrorMsg());
			}

			siteDao.remove(id);

			// 保存操作日志
			saveOperateLog(OperateDictConstants.MODEL_SITE, operateAcion, id, site.getName());

			return RespJsonFactory.buildNoContent();
		} catch (Exception e) {
			logger.error("站点" + operateAcionText + "异常", e);
			throw new APIException("站点" + operateAcionText + "异常" + e.getMessage());
		}
	}

	/**
	 * 构建站点对象
	 * 
	 * @param paramMap
	 *            请求参数
	 * @return 站点对象
	 */
	private SiteEntity buildSite(Map<String, Object> paramMap) {
		SiteEntity site = new SiteEntity();
		site.setId(PrimaryKeyUtils.uniqueId());
		site.setName(StringUtils.trim((String) paramMap.get("name")));
		site.setRegionCode((String) paramMap.get("regionCode"));
		site.setConsulIps(StringUtils.trim((String) paramMap.get("consulIps")));
		site.setConsulPort((Integer) paramMap.get("consulPort"));
		site.setConsulToken(StringUtils.trim((String) paramMap.get("consulToken")));
		site.setMgmCa(StringUtils.trim((String) paramMap.get("mgmCa")));
		site.setHorusServerCa(StringUtils.trim((String) paramMap.get("horusServerCa")));
		site.setMgmPrefix("MG");
		site.setHorusServerPrefix("HS");
		site.setCreateDateTime(systemDao.getCurrentDateTime());
		UserEntity user = getUser();
		site.setCreateUserLoginName(user.getUsername());
		return site;
	}

	/**
	 * 构建站点展示对象
	 * 
	 * @param site
	 *            站点对象
	 * @param showDetail
	 *            是否展示详情
	 * @return 站点展示对象
	 */
	private SiteDto getShowDto(SiteEntity site, boolean showDetail) {
		SiteDto siteDto = new SiteDto();
		siteDto.setId(site.getId());
		siteDto.setName(site.getName());
		siteDto.setRegionCode(site.getRegionCode());
		siteDto.setRegionText(dictTypeCache.getTextFromCache(DictTypeConstants.REGION, site.getRegionCode()));
		siteDto.setConsulIps(site.getConsulIps());
		siteDto.setConsulPort(site.getConsulPort());
		siteDto.setCreateDateTime(DateUtils.dateTimeToString(site.getCreateDateTime()));
		siteDto.setCreateLoginUserName(site.getCreateUserLoginName());
		String[] consulIpArr = site.getConsulIps().split(",");

		int critical_mgm_count = 0;
		int passing_mgm_count = 0;
		int critical_hs_count = 0;
		int passing_hs_count = 0;

		Consul consul = null;
		for (String consulIp : consulIpArr) {
			HostAndPort hostAndPort = HostAndPort.fromParts(consulIp, site.getConsulPort());
			try {
				consul = Consul.builder().withHostAndPort(hostAndPort).build();
				break;
			} catch (Exception e) {

			}
		}
		if (consul != null) {
			HealthClient healthClient = consul.healthClient();
			List<HealthCheck> healthCheck_criticals = healthClient.getChecksByState(State.FAIL).getResponse();
			for (HealthCheck healthCheck : healthCheck_criticals) {
				if (healthCheck.getServiceName().get().startsWith(site.getMgmPrefix())) {
					critical_mgm_count++;
				} else if (healthCheck.getServiceName().get().startsWith(site.getHorusServerPrefix())) {
					critical_hs_count++;
				}
			}

			List<HealthCheck> healthCheck_passings = healthClient.getChecksByState(State.PASS).getResponse();
			for (HealthCheck healthCheck : healthCheck_passings) {
				if (healthCheck.getServiceName().get().startsWith(site.getMgmPrefix())) {
					passing_mgm_count++;
				} else if (healthCheck.getServiceName().get().startsWith(site.getHorusServerPrefix())) {
					passing_hs_count++;
				}
			}
		}
		if (critical_mgm_count == 0 && passing_mgm_count != 0) {
			siteDto.setMgmStatusCode(DictConstants.STATUS_MGM_PASSING);
			siteDto.setMgmStatusText(dictTypeCache.getTextFromCache(DictTypeConstants.STATUS_MGM,
					String.valueOf(DictConstants.STATUS_MGM_PASSING)));
		} else if (critical_mgm_count != 0 && passing_mgm_count != 0) {
			siteDto.setMgmStatusCode(DictConstants.STATUS_MGM_WARNING);
			siteDto.setMgmStatusText(dictTypeCache.getTextFromCache(DictTypeConstants.STATUS_MGM,
					String.valueOf(DictConstants.STATUS_MGM_WARNING)));
		} else {
			siteDto.setMgmStatusCode(DictConstants.STATUS_MGM_CRITICAL);
			siteDto.setMgmStatusText(dictTypeCache.getTextFromCache(DictTypeConstants.STATUS_MGM,
					String.valueOf(DictConstants.STATUS_MGM_CRITICAL)));
		}

		if (critical_hs_count == 0 && passing_hs_count != 0) {
			siteDto.setHsStatusCode(DictConstants.STATUS_HS_PASSING);
			siteDto.setHsStatusText(dictTypeCache.getTextFromCache(DictTypeConstants.STATUS_HS,
					String.valueOf(DictConstants.STATUS_HS_PASSING)));
		} else if (critical_hs_count != 0 && passing_hs_count != 0) {
			siteDto.setHsStatusCode(DictConstants.STATUS_HS_WARNING);
			siteDto.setHsStatusText(dictTypeCache.getTextFromCache(DictTypeConstants.STATUS_HS,
					String.valueOf(DictConstants.STATUS_HS_WARNING)));
		} else {
			siteDto.setHsStatusCode(DictConstants.STATUS_HS_CRITICAL);
			siteDto.setHsStatusText(dictTypeCache.getTextFromCache(DictTypeConstants.STATUS_HS,
					String.valueOf(DictConstants.STATUS_HS_CRITICAL)));
		}
		return siteDto;
	}

}
